﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Web.Script.Serialization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

namespace SalesSys.Comm.Utility
{
    
    public class SimpleJson
    {
        public static ISerializerHandle CreateEx()
        {
            var jn = new JsonDotNet();
             jn.CheckWriteDepth = (p1, p2) => p1 <5;
            jn.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
            jn.DateTimeZoneHandling=DateTimeZoneHandling.Local;
            jn.Converters.Add(new IsoDateTimeConverter() { DateTimeFormat = "yyyy-MM-dd HH:mm:ss", DateTimeStyles = DateTimeStyles.None });
            return jn;
        }

        static SimpleJson()
        {
           // serializer = new DefJsonHandle();
            
            var jn = new JsonDotNet();
           // jn.CheckWriteDepth = (p1, p2) => p1 < 10;
            jn.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;

            jn.Converters.Add(new IsoDateTimeConverter() { DateTimeFormat = "yyyy-MM-dd HH:mm:ss" });
            serializer = jn;
        }

        static ISerializerHandle serializer;
        public static string Serializer(object obj)
        {
            var str = serializer.Serialize(obj,null);  
            return str;
        }
        /// <summary>
        /// 这是一个特殊序列化，默认只序列化一层，即只序列化对象的简单属性,是对象替换dto的简单处理
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="maxDepth"></param>
        /// <returns></returns>
        public static string SerializerEx(object obj,int maxDepth=1)
        {
            var jn = new JsonDotNet();
            jn.CheckWriteDepth = (p1, p2) => p1 <= maxDepth;
            jn.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
            jn.Converters.Add(new IsoDateTimeConverter() { DateTimeFormat = "yyyy-MM-dd HH:mm:ss" });
            var str = jn.Serialize(obj, null);
            return str;
        }
      
        public static object Deserialize(string str, Type type)
        {
            return serializer.Deserialize(str, type);
        }
        public static T Deserialize<T>(string str)
        {
            return serializer.Deserialize<T>(str);
        }
    }

    public interface ISerializerHandle
    {
        string Serialize(object obj,Type  type);
        object Deserialize(string str, Type type);
        T Deserialize<T>(string str);
          object Deserialize(TextReader reader, Type objectType);
          void Serialize(TextWriter textWriter, object value, Type objectType);
    }
    public class JsonDotNet : Newtonsoft.Json.JsonSerializerEx, ISerializerHandle
    {

        public string Serialize(object obj, Type type)
        {
            using (StringWriter sw = new StringWriter())
            {
                 base.Serialize(sw,obj);
                return sw.ToString();
            }
            
        }

        public object Deserialize(string str, Type type)
        {
            return Deserialize(new System.IO.StringReader(str), type);
        }

        public T Deserialize<T>(string str)
        {

            return Deserialize<T>(new JsonTextReader(new StringReader(str)));
        }
    }
    public class DefJsonHandle : JavaScriptSerializer, ISerializerHandle
    {
        public DefJsonHandle()
        {
           // this.RecursionLimit
            RegisterConverters(new[] { new DicConverter() });
        }

        /// <summary>
        /// 将Json序列化的时间由/Date(1294499956278+0800)转为本地字符串     
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string DateToLocal(string str)
        {
            str = Regex.Replace(str, @"\\/Date\((\d+)\)\\/", match =>
            {
                var dt = new DateTime(1970, 1, 1);
                dt = dt.AddMilliseconds(long.Parse(match.Groups[1].Value));
                dt = dt.ToLocalTime();
                return dt.ToString("yyyy-MM-dd HH:mm:ss");
            });
            return str;
        }
      
        public class DicConverter : JavaScriptConverter
        {

            public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
            {
                if (type == typeof(NameValueCollection) && dictionary != null)
                {
                    var nv = new NameValueCollection();
                    foreach (var item in dictionary)
                    {
                        nv.Add(item.Key, item.Value);
                    }
                    return nv;
                }
                return null;
            }

            public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
            {
                var nv = obj as NameValueCollection;
                if (nv != null)
                {
                    var dic = new Dictionary<string, object>();
                    var kvs = nv.ToKeyValueArray().Select(p => new KeyValuePair<string, object>(p.Key, p.Value));
                    dic.AddRange(kvs);
                    return dic;
                }
                return null;
            }

            public override IEnumerable<Type> SupportedTypes
            {
                get { return new[] { typeof(NameValueCollection) }; }
            }
        }

        public string Serialize(object obj, Type type)
        {
            return Serialize(obj);
        }

        #region ISerializerHandle 成员


        public object Deserialize(TextReader reader, Type objectType)
        {
            throw new NotImplementedException();
        }

        public void Serialize(TextWriter textWriter, object value, Type objectType)
        {
            throw new NotImplementedException();
        }

        #endregion
    }
}
